package com.example.event_resource_java.authority.controller.UserController;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.event_resource_java.authority.UserOpenfeign;
import com.example.event_resource_java.authority.server.UserServer;
import com.example.event_resource_java.commons.domain.UserDO;
import com.example.event_resource_java.commons.enums.Constants;
import com.example.event_resource_java.commons.enums.EnumErrorCode;
import com.example.event_resource_java.commons.model.LoginBody;
import com.example.event_resource_java.commons.util.ApiResult;
import com.example.event_resource_java.commons.util.JWTUtil;
import com.example.event_resource_java.commons.util.PasswdUtils;
import com.example.event_resource_java.commons.util.StringUtil;
import com.example.event_resource_java.commons.vo.LoginVO.TokenVO;
import com.example.event_resource_java.starinside.redis.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;


/**
 * packageName com.example.event_resource_java.authority.controller
 * 用户登录
 *
 * @author xzy
 * @version JDK 8
 * @className LoginController
 * @date 2024/4/1
 * @description
 */
@RestController
@CrossOrigin
public class LoginController {

    @Autowired
    private UserServer userServer;

    @Resource
    private UserOpenfeign userOpenfeign;

    @GetMapping("/test")
    public ApiResult testToken() {
        UserDO user = JWTUtil.getUser();
        return ApiResult.success(user);
    }

    /**
     * @auther: xzy
     * @param: 用户登录
     * @date: 2024/4/1 13:35
     */
    @CrossOrigin
    @PostMapping("/login")
    @ResponseBody
    public Object login(@RequestBody LoginBody loginBody, HttpServletResponse response) {
        loginBody.getUsername().trim();
        loginBody.getPassword().trim();

        //Base64 解密
        String password = new String(Base64.getDecoder().decode(loginBody.getPassword()));
        loginBody.setPassword(password);

        /**
         * @auther: ak
         * @Description 登录校验
         * @date: 2024/4/7 14:06
         */
        //图形验证码校验
        String loginFailCountKey = Constants.LOGIN_FAIL_KEY + loginBody.getUsername();
        String loginLimitKey = Constants.LOGIN_LIMIT_KEY + loginBody.getUsername();
        String loginMsg = userServer.verifyCode(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());
        if (!loginMsg.equals(EnumErrorCode.success.getMsg())) {
            return ApiResult.fail(EnumErrorCode.userLoginFail.getCode(), loginMsg);
        }

        // 用户身份校验
        String judge = userServer.judge(loginBody);
        if (!EnumErrorCode.success.getMsg().equals(judge)) {
            return ApiResult.fail(judge);
        }

        try {
            if (ObjectUtil.isEmpty(loginBody.getUsername())) {
                QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
                wrapper.eq("mobile", loginBody.getMobile());
                wrapper.eq("user_from", 1);
                UserDO one1 = userServer.getOne(wrapper);
                loginBody.setUsername(one1.getUsername());
            }

            QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", loginBody.getUsername());
            queryWrapper.eq("user_from", 1);
            UserDO one = userServer.getOne(queryWrapper);
//            ApiResult<?> login = userOpenfeign.login(loginBody);
            String token = userServer.getToken1(one.getMobile());
//            if (ObjectUtil.isNotNull(login.getData())) {
//                Map<String, Object> newMap;
//                try {
//                    newMap = (Map<String, Object>) login.getData();
//                } catch (Exception e) {
//                    return ApiResult.fail("登录失败，请联系管理员！");
//                }

            // 校验密码
            String pwd = PasswdUtils.get(password, one.getSalt());
            if (!pwd.equals(one.getPassword())) {
                return ApiResult.fail(EnumErrorCode.userLoginFail.getCode(), "密码错误");
            }
            TokenVO tokenVO = new TokenVO();
            tokenVO.setToken(token);
            tokenVO.setUName(one.getName());
            tokenVO.setUserName(one.getUsername());
            tokenVO.setType(one.getType());
            tokenVO.setId(one.getId());
            tokenVO.setMobile(one.getMobile());

            // 登录成功 删除登录次数限制
            RedisUtil.del(loginFailCountKey);
            RedisUtil.del(loginLimitKey);

            // 存入redis 2h
//                RedisUtil.set(Constants.LOGIN_TOKEN_KEY + one.getId(), tokenVO.getToken(), 2 * 60 * 60);
            response.setHeader("Authorization", tokenVO.getToken());

            return ApiResult.success(EnumErrorCode.userLoginSuccess.getMsg(), tokenVO);
//        } else{
//            return ApiResult.fail("账号或密码错误 请重新输入");
//        }

        } catch (
                AuthenticationException e) {
            e.printStackTrace();
            String errMsg = loginLimit(loginBody);
            return ApiResult.fail(EnumErrorCode.userLoginFail.getCode(), errMsg);
        }

    }

    /**
     * @auther: ak
     * @Description 找回密码
     * @date: 2024/4/7 14:43
     */
    @PostMapping("/forgetPassword")
    @CrossOrigin
    public ApiResult forgetPwd(@RequestBody LoginBody loginBody) {
        String msg = userServer.forgetPassword(loginBody);
        return ApiResult.success(msg);
    }

    /**
     * @auther: ak
     * @Description // 账号密码限制校验
     * @param:
     * @return:
     * @date: 2024/4/7 19:40
     */
    private String loginLimit(LoginBody loginBody) {

        String loginFailCountKey = Constants.LOGIN_FAIL_KEY + loginBody.getUsername();
        String loginLimitKey = Constants.LOGIN_LIMIT_KEY + loginBody.getUsername();

        if (RedisUtil.hasKey(loginLimitKey)) {
            return "10分钟内连续登录失败超过5次，请在" + RedisUtil.getExpire(loginLimitKey) / 60 + "分钟后重试！";
        }

        int failNum = 5;
        // 用户登录次数校验
        if (!RedisUtil.hasKey(loginFailCountKey)) {
            //首次失败登录
            RedisUtil.set(loginFailCountKey, 5);

            return "密码输入错误，10分钟内还剩" + (failNum - 1) + "次机会登陆";
        } else {
            int failCount = Integer.parseInt(RedisUtil.get(loginFailCountKey).toString());
            // 判断是否需要冻结
            if (failCount >= (failNum - 1)) {
                RedisUtil.set(loginLimitKey, "fail", 60 * 10);
                // 删除失败次数
                RedisUtil.del(loginFailCountKey);
            } else {
                RedisUtil.set(loginFailCountKey, (Integer) RedisUtil.get(loginFailCountKey) + 1);
                return EnumErrorCode.userLoginFail + "10分钟内还可重试" + (failNum - (failCount + 1)) + "次";
            }
        }
        return EnumErrorCode.success.getMsg();
    }


}